package yxy.game.pm2.module.bandit;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import yxy.apple.util.RandomUtility;
import yxy.apple.util.RandomUtility.Weight;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.crusadedate;
import yxy.cherry.data.bean.crusadedet;
import yxy.cherry.data.bean.guideinitial;
import yxy.cherry.data.bean.privilege;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.Item;
import yxy.game.pm2.bean.Privilege;
import yxy.game.pm2.bean.currency.CurrencyNotEnoughException;
import yxy.game.pm2.bean.currency.CurrencyType;
import yxy.game.pm2.bean.db.dao.MySQLCacheDAO;
import yxy.game.pm2.bean.module.PlayerModule;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.conquest.ConquestModule;
import yxy.game.pm2.module.vip.PrivilegeHandle;
import yxy.game.pm2.module.vip.PrivilegeHandle.PrivilegeType;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public class BanditModule extends PlayerModule {

	// bean===========================================================================

	private int freeTimes; // 免费刷新次数
	private int costTimes; // 付费或刷新券刷新次数
	private DateTime updateTime; // 上次刷新的时间
	private ArrayList<Bandit> taskList = new ArrayList<>();// 派遣的任务列表

	public int getFreeTimes() {
		return freeTimes;
	}

	public void setFreeTimes(int freeTimes) {
		this.freeTimes = freeTimes;
	}

	public int getCostTimes() {
		return costTimes;
	}

	public void setCostTimes(int costTimes) {
		this.costTimes = costTimes;
	}

	public DateTime getUpdateTime() {
		return updateTime;
	}

	public void setUpdateTime(DateTime updateTime) {
		this.updateTime = updateTime;
	}

	public ArrayList<Bandit> getTaskList() {
		return taskList;
	}

	public void setTaskList(ArrayList<Bandit> taskList) {
		this.taskList = taskList;
	}

	// redis==========================================================================
	private static String key(String playerCode) {
		return String.format("PLAYER:%s:MODULE:BANDIT", playerCode);
	}

	public void set() {
		try {
			setv(key(getPlayerCode()), this);
		} catch (RedisException e) {
			e.printStackTrace();
		}
	}

	static public BanditModule get(String playerCode) {
		try {
			BanditModule module = getv(key(playerCode));
			if (module == null) {
				module = MySQLCacheDAO.getV(key(playerCode), BanditModule.class);
				if(module != null){module.set();}//把数据同步到redis
			}

			if (module == null) {
				module = create(playerCode);
			}
			module.update();
			return module;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	static private BanditModule create(String playerCode) {
		BanditModule module = new BanditModule();
		module.setPlayerCode(playerCode);
		module.initTask();
		module.set();
		return module;
	}

	// func==========================================================================

	/** 初始任务 */
	private void initTask() {
		taskList.clear();
		guideinitial initialdata = DataCenter.getData(1, guideinitial.class);
		for (int i = 0; i < initialdata.getCrusadeid().length; i++) {
			Bandit task = new Bandit();
			task.setDataId(initialdata.getCrusadeid()[i]);
			taskList.add(task);
		}
	}

	public Bandit task(int taskId) {
		for (Bandit task : getTaskList()) {
			if (task.getDataId() == taskId) {
				return task;
			}
		}
		return null;
	}

	public List<String> sendingHeroList() {
		ArrayList<String> sendingList = new ArrayList<>();
		for (Bandit bandit : getTaskList()) {
			if (bandit.getDataId() <= 0) {
				continue;
			}
			if (bandit.getSendingHeroCode() != null) {
				sendingList.addAll(bandit.getSendingHeroCode());
			}
		}
		return sendingList;
	}

	public int freshFreeTimes() {
//		return fomula.剿匪每日刷新花费.intValue();
		return 3 - getFreeTimes();// TODO 剿匪每天免费刷新3次 目前是代码写死的
	}

	/** 剿匪刷新券 */
	public Currency freshItem() {
		try {
			return Item.get(getPlayerCode(), CurrencyType.CT_物品, 1030);
		} catch (Exception e) {
			return Currency.create(CurrencyType.CT_物品, 1030, 0);
		}
	}

	public void freshCost() throws CurrencyNotEnoughException {
		if (freshFreeTimes() > 0) {
			setFreeTimes(getFreeTimes() + 1);
			return;
		}
		crusadedet det = det();
		Currency cost1 = Currency.create(det.getCosttype1(), det.getCostid1(), det.getCostnum1());
		Currency cost2 = Currency.create(det.getCosttype2(), det.getCostid2(), det.getCostnum2());
		try {
			new CurrencyHandle().cost(getPlayerCode(), CCReason.剿匪, cost1);
			setCostTimes(getCostTimes() + 1);
			return;
		} catch (CurrencyNotEnoughException e) {
		}
		try {
			new CurrencyHandle().cost(getPlayerCode(), CCReason.剿匪, cost2);
			setCostTimes(getCostTimes() + 1);
			return;
		} catch (CurrencyNotEnoughException e) {
			throw e;
		}
	}

	public void freshTask() {
		ArrayList<Bandit> sendList = new ArrayList<>();
		for (Bandit task : getTaskList()) {
			if (task.getDataId() > 0 && task.getEndTime() != null) {
				// 已派遣的任务
				sendList.add(task);
			}
		}
		Collection<Duty> duties = randomDuty(-1, 10);// TODO 剿匪的任务数量 目前是代码写死的
		for (Duty duty : duties) {
			if (task(duty.id) != null) {
				continue;
			}
			Bandit task = new Bandit();
			task.setDataId(duty.id);
			sendList.add(task);
		}
		taskList = sendList;
		privilegeTask();
	}

	/** 特权任务 */
	public void privilegeTask() {
		Collection<Privilege> privileges = new PrivilegeHandle().getPrivilegeByType(getPlayerCode(), PrivilegeType.剿匪任务刷新类型);
		for (Privilege privilegeBean : privileges) {
			privilege data = DataCenter.getData(privilegeBean.getPrivilegeid(), privilege.class);
			if (getCostTimes() == data.getParameter()[0]) {
				int quality = data.getParameter()[1];
				Collection<Duty> duties = randomDuty(quality, 1);
				for (Duty duty : duties) {
					if (task(duty.id) != null) {
						continue;
					}
					Bandit task = new Bandit();
					task.setDataId(duty.id);
					getTaskList().add(task);
				}
			}
		}
	}

	/** 扫荡次数刷新 */
	public void update() {
		DateTime now = DateTime.now();
		if (getUpdateTime() == null || !new LocalDate(now).equals(new LocalDate(getUpdateTime()))) {
			try {
				if (tryLock()) {
					setUpdateTime(now);
					setFreeTimes(0);
					setCostTimes(0);
					this.set();
				}
			} catch (Exception e) {
			} finally {
				unlock();
			}
		}
	}

	public long 情报upper() {
		int upper = det().getResourcecap();
		return upper;
	}

	private crusadedet det() {
		ConquestModule conquestModule = ConquestModule.get(getPlayerCode());
		int level = conquestModule.getMapId();
		Map<String, crusadedet> crusadedetMap = DataCenter.getAllData(crusadedet.class);
		crusadedet worsedata = null;
		for (crusadedet data : crusadedetMap.values()) {
			if (worsedata == null) {
				worsedata = data;
			}
			if (level < data.getLevelmin()) {
				continue;
			}
			if (level > data.getLevelmax()) {
				continue;
			}
			return data;
		}
		return worsedata;
	}

	private Collection<Duty> randomDuty(int quality, int num) {
		crusadedet det = det();
		Map<String, crusadedate> all = DataCenter.getAllData(crusadedate.class);
		ArrayList<Duty> duties = new ArrayList<>();
		for (crusadedate data : all.values()) {
			if (quality > 0 && data.getQuality() != quality) {
				continue;
			}
			if (data.getGroup() == det.getGroup()) {
				for (int i = 0, size = data.getDutiesid().length; i < size; i++) {
					if (data.getDutiesid()[i] > 0) {
						duties.add(new Duty(data.getDutiesid()[i], data.getPercent()[i] * data.getWeight()));
					}
				}
			}
		}
		ArrayList<Duty> result = new ArrayList<>();
		RandomUtility.randomWeight(duties, result, num);
		return result;
	}

	private class Duty implements Weight {
		int id;
		int weight;

		private Duty(int id, int weight) {
			this.id = id;
			this.weight = weight;
		}

		@Override
		public int getWeight() {
			return weight;
		}
	}

	//存储到数据库的方法
	public static void saveToDB(String playerCode) {
		try {
			String key = key(playerCode);
			if (touchBucket(key).isExists()) {
				BanditModule banditModule = getv(key(playerCode));
				MySQLCacheDAO.setV(key, banditModule);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//从redis移走数据的操作
	public static void removeAllFromRedis(String playerCode) {
		try {
			touchBucket(key(playerCode)).delete();
		} catch (RedisException e) {
			e.printStackTrace();
		}
	}

	// lock==========================================================================

	@Override
	public String lockKey() {
		return String.format("lock:%s", key(getPlayerCode()));
	}
}
